﻿using System;
using System.Linq;
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;

using King.Traverse;
using King.Collections;
using King.Declarative;

[assembly: DebuggerDisplay(@"\{Type = {Type} Info = {Info} Value = {Object}}", Target = typeof(Node))]

namespace King.Traverse {
    [DebuggerTypeProxy(typeof(DebuggerEvaluationProxy))]
    internal sealed partial class Evaluation {
        object IEnumerator.Current {
            get { return Current; }
        }
    }

    public partial struct Context {

        public partial struct Enumerator {

            // IEnumerable<Context>
            object IEnumerator.Current {
                get { return Current; }
            }
            public void Dispose() {
                m_enumerator.Dispose();
            }
            public void Reset() {
                m_enumerator.Reset();
            }

            // IEnumerator<Context>
            IEnumerator<Context> IEnumerable<Context>.GetEnumerator() {
                return GetEnumerator();
            }
            IEnumerator IEnumerable.GetEnumerator() {
                return GetEnumerator();
            }
        }
    }

    internal sealed partial class AuxiliaryFrame {

        // IEnumerator<Frame>
        IEnumerator<Frame> IEnumerable<Frame>.GetEnumerator() {
            return GetEnumerator();
        }
        IEnumerator IEnumerable.GetEnumerator() {
            return ((IEnumerable<Frame>)this).GetEnumerator();
        }
    }

    internal sealed partial class Frame {
        internal Value _Current {
            get { return m_currentChild.Value; }
        }
        
        // IEnumerable<Node>
        object IEnumerator.Current {
            get { return Current; }
        }
        public void Dispose() {
            throw new NotSupportedException();
        }
        public void Reset() {
            throw new NotSupportedException();
        }

        // ISoundable<Frame>
        int IStackable<Frame>.Depth {
            get { return Depth; }
        }

        // ILinkable<Frame>
        Frame ILinkable<Frame>.Value {
            get { return this; }
        }
        ILinkable<Frame> ILinkable<Frame>.Next {
            get { return Next; }
        }
        IStackable<Frame> IStackable<Frame>.Next {
            get { return Next; }
        }

        // IEnumerable<Frame>
        IEnumerator<Frame> IEnumerable<Frame>.GetEnumerator() {
            return GetEnumerator();
        }
        IEnumerator IEnumerable.GetEnumerator() {
            return ((IEnumerable<Frame>)this).GetEnumerator();
        }

        private string ToStringDebug() {
            var value = "depth = " + m_depth + " child = " + m__nextChildIndex;

            if (m_nextLogicalSubstitute != null) {
                if (m_nextLogicalSubstitute.m_depth > m_depth + 1)
                    value += " continue @ " + m_nextLogicalSubstitute.m_depth;
            }

            var flags = new List<string>();
            if (m_implementsSubstitute) flags.Add("substitute");
            if (flags.Any())
                value += " {" + string.Join(" | ", flags.ToArray()) + "}";

            return value;
        }
    }
}